<template>
    <div class="component-upload-image">
        <el-upload
            ref="imageUpload"
            multiple
            :action="uploadImgUrl"
            list-type="picture-card"
            :on-success="handleUploadSuccess"
            :before-upload="handleBeforeUpload"
            :limit="limit"
            :on-error="handleUploadError"
            :on-exceed="handleExceed"
            :before-remove="handleDelete"
            :show-file-list="true"
            :headers="headers"
            :file-list="fileList"
            :on-preview="handlePictureCardPreview"
            :class="{ hide: fileList.length >= limit }"
        >
            <i class="el-icon-plus avatar-uploader-icon"></i>
        </el-upload>

        <div class="el-upload__tip" v-if="showTip">
            请上传
            <template v-if="fileSize">
                大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
            </template>
            <template v-if="fileType">
                格式为 <b style="color: #f56c6c">{{ fileType.join('/') }}</b>
            </template>
            的文件
        </div>

        <el-dialog
            :visible.sync="dialogVisible"
            title="预览"
            width="800px"
            append-to-body
        >
            <img
                :src="dialogImageUrl"
                style="display: block; max-width: 100%; margin: 0 auto"
                alt=""
            />
        </el-dialog>
    </div>
</template>

<script>
import { getToken } from "@/utils/auth";
import { delOss, listByIds } from "@/api/oss";
import { Message } from "element-ui";

export default {
    name: "UploadImage",
    props: {
        value: [String, Array],
        limit: {
            type: Number,
            default: 5,
        },
        fileSize: {
            type: Number,
            default: 5,
        },
        fileType: {
            type: Array,
            default: () => ["png", "jpg", "jpeg"],
        },
        isShowTip: {
            type: Boolean,
            default: true,
        },
    },
    data() {
        return {
            imageUpload: null,
            baseUrl: process.env.VUE_APP_BASE_API,
            uploadImgUrl: process.env.VUE_APP_BASE_API + "/oss/upload",
            headers: {
                Authorization: "Bearer " + getToken(),
            },
            fileList: [],
            uploadList: [],
            dialogImageUrl: "",
            dialogVisible: false,
            number: 0,
        };
    },
    computed: {
        showTip() {
            return this.isShowTip && (this.fileSize || this.fileType.length);
        },
    },
    watch: {
        value: {
            handler: "initFileList",
            immediate: true,
        },
    },
    methods: {
        initFileList(val) {
            if (!val) {
                this.fileList = [];
                return;
            }

            if (Array.isArray(val)) {
                this.fileList = val.map(item => ({
                    name: item.ossId || item,
                    url: item.url ? this.baseUrl + item.url : this.baseUrl + item,
                    ossId: item.ossId,
                }));
            } else {
                listByIds(val).then(res => {
                    this.fileList = res.data.map(item => ({
                        name: item.ossId,
                        url: this.baseUrl + item.url,
                        ossId: item.ossId,
                    }));
                });
            }
        },
        handleBeforeUpload(file) {
            let isImg = true;
            let fileExtension = file.name.split('.').pop().toLowerCase();
            if (this.fileType.length) {
                isImg = this.fileType.includes(fileExtension);
            }
            if (!isImg) {
                Message.error(`文件格式不正确, 请上传 ${this.fileType.join("/")} 格式的图片`);
                return false;
            }

            if (this.fileSize && file.size / 1024 / 1024 > this.fileSize) {
                Message.error(`上传图片大小不能超过 ${this.fileSize}MB!`);
                return false;
            }

            this.number++;
            this.$emit("loading", true);
        },
        handleExceed() {
            Message.error(`上传文件数量不能超过 ${this.limit} 个!`);
        },
        handleUploadSuccess(res, file) {
            if (res.code === 200) {
                this.uploadList.push({
                    name: res.data.fileName,
                    url: res.data.url,
                    ossId: res.data.ossId,
                });
                this.uploadedSuccessfully();
            } else {
                this.number--;
                this.$emit("loading", false);
                Message.error(res.msg || "上传失败");
                this.$refs.imageUpload.handleRemove(file);
                this.uploadedSuccessfully();
            }
        },
        handleUploadError() {
            Message.error("上传失败");
            this.$emit("loading", false);
        },
        handleDelete(file, fileList) {
            const index = this.fileList.findIndex(f => f.name === file.name);
            if (index !== -1) {
                let ossId = this.fileList[index].ossId;
                if (ossId) delOss(ossId);
                this.fileList.splice(index, 1);
                this.$emit("input", this.listToString(this.fileList));
            }
            return false;
        },
        handlePictureCardPreview(file) {
            this.dialogImageUrl = file.url;
            this.dialogVisible = true;
        },
        uploadedSuccessfully() {
            if (this.number > 0 && this.uploadList.length === this.number) {
                this.fileList = this.fileList.filter(f => f.url).concat(this.uploadList);
                this.uploadList = [];
                this.number = 0;
                this.$emit("loading", false);
                this.$emit("input", this.listToString(this.fileList));
                this.$emit("over", "success");
                Message.success("上传成功");
            }
        },
        listToString(list, separator = ",") {
            return list
                .filter(item => item.ossId && !item.url.startsWith("blob:"))
                .map(item => item.ossId)
                .join(separator);
        },
    },
};
</script>

<style scoped lang="scss">
// .el-upload--picture-card 控制加号部分
 .hide .el-upload--picture-card {
    display: none;
}
</style>
